import sys
from datetime import datetime, timedelta

import psycopg2


class ReadYatLog:
    def __init__(self):
        self.schd_start_time = ''
        self.schd_run_time = ''
        self.schd_end_time = ''
        self.schd_pass_num = 0
        self.schd_fail_num = 0
        self.schd_block_num = 0
        self.schd_total_num = 0
        self.case_info = list()
        self.schd_info = ''
        self.tester = {"FU_AC_JDBC": "",
                       "FU_AC_ODBC": "",
                       "FU_AC_PYTHON": "",
                       "FU_SQ_GRAM": "",
                       "FU_SQ_PROC": "",
                       "FU_SQ_SYS": "",
                       "FU_SQ_PERF": "",
                       "FU_SQ_KEYWORD": "",
                       "FU_ST_INDEX": "",
                       "FU_ST_PART": "",
                       "FU_ST_MOT": "",
                       "FU_ST_MATER": "",
                       "FU_ST_FULLINDEX": "",
                       "DF_MA_DROPNODE": "",
                       "DF_MA_UPGRADE": "",
                       "DF_MA_TOOLS": "",
                       "DF_SE_IDENTITY": "",
                       "DF_SE_VISIT": "",
                       "DF_SE_THREE": "",
                       "DF_SE_AUDIT": "",
                       "DF_SE_MODIFY": "",
                       "DF_SE_ENCRYPT": "",
                       "DF_SE_MASK": "",
                       "DF_SE_ATTACK": "",
                       "DF_HA_BACKUP": "",
                       "DF_HA_DELAYBACK": "",
                       "DF_HA_DUMP": "",
                       "DF_HA_COPY": "",
                       "DF_HA_GUC": ""}

    def read_yat_log(self, **kwargs):
        with open(kwargs['path'], 'r', encoding='utf-8',
                  errors='ignore') as f:
            for line in f.readlines():
                line_len = len(line.split())
                if line_len == 4:
                    self.schd_start_time = ' '.join(line.split()[1:3])
                elif line_len == 11:
                    self.schd_end_time = ' '.join(line.split()[-3:-1])
                    self.schd_run_time = line.split()[6].strip('PT')
                elif line_len in [9, 10]:
                    case_name = line.split()[6].split('/')[-1]
                    case_status = line.split()[-1]
                    case_start_time = ' '.join(line.split()[1:3:]).strip(
                        '[').strip(']')
                    case_run_time = ''.join(line.split()[3:5:]).strip(
                        '[').strip(']')

                    t_format = "%Y-%m-%d %H:%M:%S"
                    tmp_start = datetime.strptime(case_start_time, t_format)
                    tmp_run = float(case_run_time[:-1:])
                    if case_run_time.endswith('h'):
                        case_end_time = (tmp_start + timedelta(
                            hours=tmp_run)).strftime(t_format)
                    elif case_run_time.endswith('m'):
                        case_end_time = (tmp_start + timedelta(
                            minutes=tmp_run)).strftime(t_format)
                    elif case_run_time.endswith('s'):
                        case_end_time = (tmp_start + timedelta(
                            seconds=tmp_run)).strftime(t_format)
                    else:
                        case_end_time = case_start_time

                    if kwargs['schd_name'].endswith('_PY'):
                        schd = kwargs['schd_name'][:-3:]
                    elif kwargs['schd_name'].endswith('_SQL'):
                        schd = kwargs['schd_name'][:-4:]
                    elif kwargs['schd_name'].count('_PY_') == 1:
                        schd = kwargs['schd_name'].split('_PY_')[0]
                    else:
                        schd = kwargs['schd_name'].split('_SQL_')[0]
                    tester = self.tester.get(schd, '')

                    self.case_info.append(f"('{kwargs['run_os']}', "
                                          f"'{kwargs['schd_name']}', "
                                          f"'{case_name}', "
                                          f"'{case_status}', "
                                          f"'{case_start_time}', "
                                          f"'{case_run_time}', "
                                          f"'用例问题', "
                                          f"'{tester}', "
                                          f"'未解决', "
                                          f"'{kwargs['ip_host']}', "
                                          f"'{kwargs['console_url']}', "
                                          f"'{case_end_time}', "
                                          f"'{kwargs['log_url']}')")

                    if case_status == 'er':
                        self.schd_fail_num += 1
                    elif case_status == 'to':
                        self.schd_block_num += 1
                    else:
                        self.schd_pass_num += 1
        self.schd_total_num = sum(
            [self.schd_pass_num, self.schd_fail_num, self.schd_block_num])

        self.schd_info += f"('{kwargs['run_os']}', " \
            f"'{kwargs['schd_name']}', " \
            f"'{self.schd_total_num}', " \
            f"'{self.schd_pass_num}', " \
            f"'{self.schd_fail_num}', " \
            f"'{self.schd_block_num}', " \
            f"'{self.schd_start_time}', " \
            f"interval '{self.schd_run_time}', " \
            f"'{kwargs['ip_host']}', " \
            f"'{kwargs['core_num']}')"


class DbOperate:
    def __init__(self, **dbinfo):
        self.db_info = dbinfo
        self.conn = None
        self.cur = None

    def conn_db(self):
        self.conn = psycopg2.connect(database=self.db_info['db_name'],
                                     user=self.db_info['db_user'],
                                     password=self.db_info['db_password'],
                                     host=self.db_info['db_host'],
                                     port=self.db_info['port'])
        self.conn.set_client_encoding('utf-8')
        self.cur = self.conn.cursor()
        # connect successful")

    def exec_dml_sql(self, sql_cmd):
        print(sql_cmd)
        self.cur.execute(sql_cmd)
        self.conn.commit()
        # dml operate successful")

    def exec_dql_sql(self, sql_cmd):
        self.cur.execute(sql_cmd)
        rows = self.cur.fetchall()
        # select successful")
        return rows

    def close_conn(self):
        self.conn.close()
        # close connect successful")


if __name__ == '__main__':
    Usage = f"Usage:input as 'python3 {sys.argv[0]} schd_name yat_log_path " \
        f"run_os ip_host core_num console_url run_model_table " \
        f"run_info_table his_model_table his_info_table " \
        f"report_db_name report_db_user report_db_password report_db_host" \
        f"report_port' "
    if len(sys.argv) < 10:
        print(Usage)
        exit(0)

    tem_dict = dict()
    tem_dict['schd_name'] = sys.argv[1]
    tem_dict['path'] = sys.argv[2]
    tem_dict['run_os'] = sys.argv[3]
    tem_dict['ip_host'] = sys.argv[4]
    tem_dict['core_num'] = sys.argv[5]
    tem_dict['console_url'] = sys.argv[6]
    tem_dict['run_model_table'] = sys.argv[7]
    tem_dict['run_info_table'] = sys.argv[8]
    tem_dict['his_model_table'] = sys.argv[9]
    tem_dict['his_info_table'] = sys.argv[10]
    tem_dict['log_url'] = sys.argv[16]
    read_res = ReadYatLog()
    read_res.read_yat_log(**tem_dict)
    print(read_res.schd_info)

    db_info = {'db_name': sys.argv[11],
               'db_user': sys.argv[12],
               'db_password': sys.argv[13],
               'db_host': sys.argv[14],
               'port': sys.argv[15]}
    my_db = DbOperate(**db_info)
    my_db.conn_db()
    # noinspection PyBroadException
    try:
        # 删除一月前的数据
        delete_his_sql = ""
        for his_t in [tem_dict['his_model_table'], tem_dict['his_info_table']]:
            delete_his_sql += f"delete from \"{his_t}\" as n " \
                f"where n.start_time < to_timestamp(substring(" \
                f"to_char(now(), 'yyyy-MM-DD hh24:MI:ss') from 1 for 10), " \
                f"'yyyy-MM-dd') - interval '30d';"

        # 转移model表数据到历史表
        trans_model_sql = f"insert into \"{tem_dict['his_model_table']}\"(" \
            f"run_os, model_name, total_num, pass_num, fail_num, " \
            f"block_num, start_time, run_time, ip_name, core_num) " \
            f"select run_os, model_name, total_num, pass_num, fail_num, " \
            f"block_num, start_time, run_time, ip_name, core_num " \
            f"from \"{tem_dict['run_model_table']}\" " \
            f"where model_name='{tem_dict['schd_name']}' " \
            f"and run_os='{tem_dict['run_os']}';"

        # 删除model表中已转移数据
        delete_model_sql = f"delete from \"{tem_dict['run_model_table']}\" " \
            f"where model_name='{tem_dict['schd_name']}' " \
            f"and run_os='{tem_dict['run_os']}';"

        # 转移info表数据到历史表
        trans_info_sql = f"insert into \"{tem_dict['his_info_table']}\"(" \
            f"run_os, model_name, tc_name, run_result, start_time, " \
            f"run_time, failed_reason, solution, problem_type, " \
            f"issue_no, develop_owner, test_owner, status, " \
            f"ip_name, jenkins_link, end_time, log_link) " \
            f"select run_os, model_name, tc_name, run_result, start_time, " \
            f"run_time, failed_reason, solution, problem_type, " \
            f"issue_no, develop_owner, test_owner, status, " \
            f"ip_name, jenkins_link, end_time, log_link " \
            f"from \"{tem_dict['run_info_table']}\" " \
            f"where model_name='{tem_dict['schd_name']}' " \
            f"and run_os='{tem_dict['run_os']}';"

        # 删除info表中已转移数据
        delete_info_sql = f"delete from \"{tem_dict['run_info_table']}\" " \
            f"where model_name='{tem_dict['schd_name']}' " \
            f"and run_os='{tem_dict['run_os']}';"

        # 写入model表
        insert_model_sql = f"insert into \"{tem_dict['run_model_table']}\"(" \
            f"run_os, model_name, total_num, pass_num, fail_num, " \
            f"block_num, start_time, run_time, ip_name, core_num) " \
            f"values {read_res.schd_info}; "

        # 写入info表
        insert_info_sql = f"insert into \"{tem_dict['run_info_table']}\"(" \
            f"run_os, model_name, tc_name, run_result, start_time, " \
            f"run_time, problem_type, test_owner, status, ip_name, " \
            f"jenkins_link, end_time, log_link) " \
            f"values {','.join(read_res.case_info)};"

        exec_sql = f"begin; {delete_his_sql} {trans_model_sql} " \
            f"{delete_model_sql}  {trans_info_sql} " \
            f"{delete_info_sql} {insert_model_sql} " \
            f"{insert_info_sql} end;"
        my_db.exec_dml_sql(exec_sql)
    except Exception:
        print(Exception)
    finally:
        my_db.close_conn()
